跳到主要内容

Components

Props

Props 修改组件的行为和外观。它们作为 key args 传递给一个 Component

一般的 HTML 标准属性都能通过 props 传递

rx.box(
"Hello World",
id="box-id",
class_name=[
"class-name-1",
"class-name-2",
],
)

css 的样式属性当然也不在话下

rx.button(
"Fancy Button",
border_radius="1em",
box_shadow="rgba(151, 65, 252, 0.8) 0 15px 30px -10px",
background_image="linear-gradient(144deg,#AF40FF,#5B42F3 50%,#00DDEB)",
box_sizing="border-box",
color="white",
opacity=1,
)

State 变量可以绑定到 props,以便页面始终反映应用程序的当前状态。

class PropExampleState(rx.State):
text: str = "Hello World"
color: str = "red"

@rx.event
def flip_color(self):
if self.color == "red":
self.color = "blue"
else:
self.color = "red"


def index():
return rx.button(
PropExampleState.text,
color_scheme=PropExampleState.color,
on_click=PropExampleState.flip_color,
)

Conditional Rendering 条件渲染

rx.cond 条件组件

我们不能在 Reflex 中使用 Python if/else 语句来引用状态变量。为了解决这个问题,使用 rx.cond 组件根据状态变量的值有条件地渲染组件或设置属性。

class CondSimpleState(rx.State):
show: bool = True

@rx.event
def change(self):
self.show = not (self.show)


def cond_simple_example():
return rx.vstack(
rx.button(
"Toggle", on_click=CondSimpleState.change
),
rx.cond(
CondSimpleState.show,
rx.text("Text 1", color="blue"),
rx.text("Text 2", color="red"),
),
)

rx.cond 接受三个参数:一个条件两个组件,如果条件为 True,则显示第一个组件,反之亦然;第二个组件可为空,即条件为 False 时展示空白

Conditional Props 条件属性

还可以使用 rx.cond 为 props 设置条件属性。在这个例子中,我们根据状态变量 PropCondState.value 的值设置文本组件的 color 属性。

class PropCondState(rx.State):
value: int

@rx.event
def set_end(self, value: list[int]):
self.value = value[0]


def cond_prop():
return rx.slider(
default_value=[50],
on_value_commit=PropCondState.set_end,
color_scheme=rx.cond(
PropCondState.value > 50, "green", "pink"
),
width="100%",
)

额外语法

use the logical operator ~ to negate a condition.

rx.vstack(
rx.button("Toggle", on_click=CondState.change),
rx.cond(
CondState.show,
rx.text("Text 1", color="blue"),
rx.text("Text 2", color="red"),
),
rx.cond(
~CondState.show,
rx.text("Text 1", color="blue"),
rx.text("Text 2", color="red"),
),
)

也可嵌套 nested 使用(有点丑)

import random


class NestedState(rx.State):
num: int = 0

def change(self):
self.num = random.randint(-10, 10)


def cond_nested_example():
return rx.vstack(
rx.button("Toggle", on_click=NestedState.change),
rx.cond(
NestedState.num > 0,
rx.text(
f"{NestedState.num} is Positive!",
color="orange",
),
rx.cond(
NestedState.num == 0,
rx.text(
f"{NestedState.num} is Zero!",
color="blue",
),
rx.text(
f"{NestedState.num} is Negative!",
color="red",
),
),
),
)

rx.match 多条件组件

Multiple Conditional Statements 多条件语句

Reflex 中的 rx.match 组件为处理多个条件语句和结构模式匹配提供了一个强大的替代方案,优于 rx.cond 。与嵌套的 rx.cond 结构相比,该组件允许您以更清晰、更易读的方式处理多个条件及其相关组件。

from typing import List

import reflex as rx


class MatchState(rx.State):
cat_breed: str = ""
animal_options: List[str] = [
"persian",
"siamese",
"maine coon",
"ragdoll",
"pug",
"corgi",
]


def match_demo():
return rx.flex(
rx.match(
MatchState.cat_breed,
("persian", rx.text("Persian cat selected.")),
("siamese", rx.text("Siamese cat selected.")),
(
"maine coon",
rx.text("Maine Coon cat selected."),
),
("ragdoll", rx.text("Ragdoll cat selected.")),
rx.text("Unknown cat breed selected."),
),
rx.select(
[
"persian",
"siamese",
"maine coon",
"ragdoll",
"pug",
"corgi",
],
value=MatchState.cat_breed,
on_change=MatchState.set_cat_breed,
),
direction="column",
gap="2",
)

Rendering Iterables 迭代渲染

使用 rx.foreach 组件从可迭代对象中渲染组件,以实现 for 循环的效果

class IterState(rx.State):
color: list[str] = [
"red",
"green",
"blue",
]


def colored_box(color: str):
return rx.button(color, background_color=color)


def dynamic_buttons():
return rx.vstack(
rx.foreach(IterState.color, colored_box),
)

# 或者使用 lambda
def dynamic_buttons():
return rx.vstack(
rx.foreach(
IterState.color,
lambda color: colored_box(color),
),
)

使用 lambda 时,就无需定义单独的 components 生成函数了:

def dynamic_buttons():
return rx.vstack(
rx.foreach(
IterState.color,
lambda color: rx.button(
color, background_color=color
),
),
)

For vs Foreach

  • Regular For Loop:在遍历常量时使用
  • Foreach:在迭代状态变量时使用

上一个例子中,由于数据 IterState.color 是常量,所以可以使用 for loop 来写:

colors = ["red", "green", "blue"]


def dynamic_buttons_for():
return rx.vstack(
[colored_box(color) for color in colors],
)

然而,一旦数据是动态的,那就必须使用 rx.foreach

class DynamicIterState(rx.State):
color: list[str] = [
"red",
"green",
"blue",
]

def add_color(self, form_data):
self.color.append(form_data["color"])


def dynamic_buttons_foreach():
return rx.vstack(
rx.foreach(DynamicIterState.color, colored_box),
rx.form(
rx.input(
name="color", placeholder="Add a color"
),
rx.button("Add"),
on_submit=DynamicIterState.add_color,
),
)

image-20250217170735921

Render Function 渲染函数

渲染每个 item 的函数可以定义为单独的函数或作为 lambda 函数

class IterState2(rx.State):
color: list[str] = [
"red",
"green",
"blue",
]


def colored_box(color: rx.Var[str]):
return rx.button(color, background_color=color)


def dynamic_buttons2():
return rx.vstack(
rx.foreach(IterState2.color, colored_box),
)

注意 colored_box 的参数 color 的类型被定义为 rx.Var[str], This is what allows us to compile the frontend without knowing the actual value of the state var (which is only known at runtime)

Enumerating Iterables 枚举可迭代对象

渲染函数还可以接受索引作为第二个参数,这意味着我们可以像下面的示例中所示枚举数据:

image-20250217171220469

class IterIndexState(rx.State):
color: list[str] = [
"red",
"green",
"blue",
]


def create_button(color: rx.Var[str], index: int):
return rx.box(
rx.button(f"{index + 1}. {color}"),
padding_y="0.5em",
)


def enumerate_foreach():
return rx.vstack(
rx.foreach(IterIndexState.color, create_button),
)

# in lambda
def enumerate_foreach():
return rx.vstack(
rx.foreach(
IterIndexState.color,
lambda color, index: create_button(
color, index
),
),
)

Iterating Dictionaries 迭代字典

当然,foreach 还可以迭代字典

image-20250217171418633

class SimpleDictIterState(rx.State):
color_chart: dict[str, str] = {
"sky": "blue",
"balloon": "red",
"grass": "green",
}


def display_color(color: list):
# color is presented as a list key-value pairs [("sky", "blue"), ("balloon", "red"), ("grass", "green")]
return rx.box(
rx.text(color[0]), bg=color[1], padding_x="1.5em"
)


def dict_foreach():
return rx.grid(
rx.foreach(
SimpleDictIterState.color_chart,
display_color,
),
columns="3",
)

Nested examples 嵌套示例

image-20250217171748506

class NestedStateFE(rx.State):
projects: list[dict[str, list]] = [
{
"technologies": [
"Next.js",
"Prisma",
"Tailwind",
"Google Cloud",
"Docker",
"MySQL",
]
},
{
"technologies": [
"Python",
"Flask",
"Google Cloud",
"Docker",
]
},
]


def get_badge(technology: rx.Var[str]) -> rx.Component:
return rx.badge(
technology, variant="soft", color_scheme="green"
)


def project_item(
project: rx.Var[dict[str, list]]
) -> rx.Component:
return rx.box(
rx.hstack(
rx.foreach(project["technologies"], get_badge)
),
)


def projects_example() -> rx.Component:
return rx.box(
rx.foreach(NestedStateFE.projects, project_item)
)

另一个例子

image-20250217171922345

class NestedDictIterState(rx.State):
color_chart: dict[str, list[str]] = {
"purple": ["red", "blue"],
"orange": ["yellow", "red"],
"green": ["blue", "yellow"],
}


def display_colors(color: rx.Var[tuple[str, list[str]]]):
return rx.vstack(
rx.text(color[0], color=color[0]),
rx.hstack(
rx.foreach(
color[1],
lambda x: rx.box(
rx.text(x, color="black"), bg=x
),
)
),
)


def nested_dict_foreach():
return rx.grid(
rx.foreach(
NestedDictIterState.color_chart,
display_colors,
),
columns="3",
)

Foreach with Cond

我们也可以同时使用 foreachcond 组件

image-20250217172023169

import dataclasses


@dataclasses.dataclass
class ToDoListItem:
item_name: str
is_packed: bool


class ForeachCondState(rx.State):
to_do_list: list[ToDoListItem] = [
ToDoListItem(
item_name="Space suit", is_packed=True
),
ToDoListItem(item_name="Helmet", is_packed=True),
ToDoListItem(
item_name="Back Pack", is_packed=False
),
]


def render_item(item: rx.Var[ToDoListItem]):
return rx.cond(
item.is_packed,
rx.list.item(item.item_name + " ✔"),
rx.list.item(item.item_name),
)


def packing_list():
return rx.vstack(
rx.text("Sammy's Packing List"),
rx.list(
rx.foreach(
ForeachCondState.to_do_list, render_item
)
),
)